﻿define([
    'dojo/_base/declare',
    'geomap/plugins/layers/ExGraphicsLayer',
    'esri/symbols/CartographicLineSymbol',
    'esri/symbols/SimpleLineSymbol',
    'esri/geometry/Polyline',
    'esri/graphic',
], function (declare, GraphicsLayer, CartographicLineSymbol, SimpleLineSymbol, Polyline, Graphic) {
    var PolylineLayer = declare([GraphicsLayer], {
        setData: function (mapUtils, layer) {
            var me = this;
            me.clear();
            if (!mapUtils) {
                return;
            }
            me.mapUtils = mapUtils;
            me._setLayer(layer);
            var options = layer.layer || {};
            me.options = options;
            var data = $.extend(true, [], options.data);
            me.highlightOptions = Object.assign(
                {
                    visible: false,
                    symbol: {
                        type: 'simplePolyline',
                        color: [0, 255, 255],
                        style: 'solid',
                        width: 2,
                    },
                },
                options.highlightOptions
            );

            me.popupOptions = Object.assign(
                {
                    visible: false,
                    isMultiPopup: false,
                    contentField: 'content',
                    isShowCloseIcon: false,
                },
                options.popupOptions
            );

            me.__currentGraphics = [];
            if (me.__mapOnLoadHandle) {
                clearInterval(me.__mapOnLoadHandle);
            }

            me.__mapOnLoadHandle = setInterval(function () {
                if (mapUtils.getMap().loaded) {
                    clearInterval(me.__mapOnLoadHandle);
                    if (!data || data.length < 1) {
                        if (typeof options.callback == 'function') {
                            options.callback(layer);
                        }
                    } else {
                        var symbolFieldName = options.symbolFieldName || 'symbol';
                        var pathsFieldName = options.pathsFieldName || 'paths';
                        var spatialReference = me.spatialReference;

                        data.map(function (item, index) {
                            // const polyline = {
                            //     type: 'polyline',
                            //     paths: [],
                            // };
                            if (pathsFieldName) {
                                item.paths = item[pathsFieldName];
                            }
                            if (item.paths && item.paths.length > 0) {
                                var polyline = me.createPolyline(item, {
                                    sr: spatialReference,
                                });
                                var symbolItem = item[symbolFieldName] || options.symbol;
                                let symbol = me.createSymbol(symbolItem);
                                var attributes = item;
                                if (!item.x || !item.y) {
                                    var center = polyline.getPoint(0, 1); //polyline.getExtent().getCenter(); //
                                    item.x = center.x;
                                    item.y = center.y;
                                }

                                var graphic = me.createGraphic({
                                    geometry: polyline,
                                    symbol: symbol,
                                    attributes: attributes,
                                });
                                me.add(graphic);
                                if (index == data.length - 1) {
                                    me._calCurrentGraphics();
                                    if (options.labelOptions) {
                                        me.labelOptions = mapUtils.$.extend(
                                            true,
                                            {
                                                textField: 'name',
                                                ptThreshold: 0, //当前窗口的点位少于这个最大值时，标签强制展示
                                                showLabels: 1, //1:根据比例尺展示，2：强制展示，0：强制不展示
                                                scaleInfo: { minScale: 0, maxScale: 0 },
                                                labelSymbol: {
                                                    labelClass: 'labelInfo',
                                                    labelStyle: {
                                                        offsety: 18,
                                                        offsetx: 0,
                                                        position: 'top',
                                                    },
                                                },
                                            },
                                            options.labelOptions
                                        );
                                        me._showLabels(mapView, options);
                                    }
                                    if (options.popupOptions && options.popupOptions.visible) {
                                        me.openCustomPopup(mapView, data);
                                    }
                                    if (typeof options.callback == 'function') {
                                        options.callback(layer);
                                    }
                                }

                                //如果有动态分割点位就添加动态点效果
                                // if (options.splitPoint) {
                                //     let list = [];
                                //     item.paths.forEach((path) => {
                                //         list = me.addArrow({ paths: path, ...options.splitPoint });
                                //         pointList.push(...list);
                                //     })
                                // }
                            }
                        });
                        if (options.splitPoint) {
                            me.addSplitPointLayer(data);
                        }

                        me._showHighlight(mapUtils, options);

                        me._handleList = me._handleList || [];
                        let zoomEndHandle = me.mapUtils.getMap().on('zoom-end', () => {
                            if (options.splitPoint) {
                                me.addSplitPointLayer(data);
                            } else {
                                zoomEndHandle.remove();
                                zoomEndHandle = null;
                            }
                        });
                        me._handleList.push(zoomEndHandle);
                    }
                }
            });
        },
        //添加分割点图层
        addSplitPointLayer(data) {
            var mapView = this.mapView;
            let layerName = this.options.layerName + '_splitPoint';
            mapView.removeLayer(layerName);

            let pointList = this.getSplitPoint(data);
            if (!pointList.length) return;
            let { minScale, maxScale } = this.options.splitPoint || {};

            mapView.addLayer('pointLayer', {
                layerName: layerName,
                data: pointList,
                minScale,
                maxScale,
            });
        },
        //获取路线分割点位
        getSplitPoint(data) {
            let pointList = [];
            let splitPoint = this.options.splitPoint;
            data.forEach(item => {
                let list = [];
                item.paths.forEach(path => {
                    list = this.addArrow({ paths: path, ...splitPoint });
                    pointList.push(...list);
                });
            });
            return pointList;
        },
        //按开始点添加箭头
        // addArrowByStartPoint({
        //     paths,
        //     symbol = {
        //         type: 'simplePoint',
        //         color: [255, 255, 255],
        //         size: 8,
        //         path: 'M15.233058 836.12562l172.641322 172.641322c18.618182 18.618182 50.77686 18.618182 71.087603 0l545.004959-545.004959 545.004959 545.004959c18.618182 18.618182 50.77686 18.618182 71.087603 0l172.641322-172.641322c18.618182-18.618182 18.618182-50.77686 0-71.087603L1015.53719 192.952066c-1.692562-1.692562-3.385124-5.077686-5.077686-6.770248L837.818182 13.540496c-10.155372-8.46281-22.003306-13.540496-35.543802-13.540496s-25.38843 5.077686-35.543801 15.233058L594.089256 186.181818c-1.692562 1.692562-3.385124 3.385124-5.077686 6.770248L15.233058 766.730579c-18.618182 18.618182-18.618182 50.77686 0 69.395041z'
        //     }
        // } = {}) {
        //     let point,
        //         angle,
        //         pointList = [];
        //     for (let i = 0; i < paths.length; i++) {
        //         point = { x: paths[i][0], y: paths[i][1] };
        //         if (paths[i + 1]) {
        //             angle = this.getPointAngle(point, paths[i + 1]);
        //             point.symbol = Object.assign({}, symbol);
        //             point.symbol.angle = angle;
        //             pointList.push(point);
        //         }
        //     }
        //     return pointList;
        // },
        //添加箭头
        addArrow({
            paths,
            segmentLength = 20000,
            symbol = {
                type: 'simplePoint',
                color: [255, 255, 255],
                size: 8,
                path: 'M15.233058 836.12562l172.641322 172.641322c18.618182 18.618182 50.77686 18.618182 71.087603 0l545.004959-545.004959 545.004959 545.004959c18.618182 18.618182 50.77686 18.618182 71.087603 0l172.641322-172.641322c18.618182-18.618182 18.618182-50.77686 0-71.087603L1015.53719 192.952066c-1.692562-1.692562-3.385124-5.077686-5.077686-6.770248L837.818182 13.540496c-10.155372-8.46281-22.003306-13.540496-35.543802-13.540496s-25.38843 5.077686-35.543801 15.233058L594.089256 186.181818c-1.692562 1.692562-3.385124 3.385124-5.077686 6.770248L15.233058 766.730579c-18.618182 18.618182-18.618182 50.77686 0 69.395041z',
                // path: 'M910.222222 796.444444c-17.066667 0-34.133333-5.688889-45.511111-17.066666L551.822222 409.6c-11.377778-5.688889-17.066667-11.377778-34.133333-11.377778-5.688889 0-22.755556 5.688889-28.444445 11.377778l-329.955555 364.088889c-22.755556 22.755556-56.888889 22.755556-79.644445 5.688889-22.755556-22.755556-22.755556-56.888889-5.688888-79.644445l329.955555-364.088889c28.444444-34.133333 73.955556-51.2 119.466667-51.2s85.333333 22.755556 119.466666 56.888889l312.888889 364.088889c22.755556 22.755556 17.066667 56.888889-5.688889 79.644445-11.377778 5.688889-28.444444 11.377778-39.822222 11.377777z'
            },
            options = {
                units: 'meters',
            },
        } = {}) {
            var mapUtils = this.mapUtils;

            let start = paths[0];
            let end = paths[paths.length - 1];
            let point_strat = { x: start[0], y: start[1] };
            let point_end = { x: end[0], y: end[1] };

            let level = mapUtils.getMap().getLevel();

            // 方案二
            let levelType = {
                // 12: { segmentLength: 200 },
                // 13: { segmentLength: 100 },
                // 14: { segmentLength: 50 },
                // 15: { segmentLength: 25 },
                // 16: { segmentLength: 20 },
                // 17: { segmentLength: 15 }
                8: { segmentLength: 5000 },
                9: { segmentLength: 4000 },
                10: { segmentLength: 3000 },
                11: { segmentLength: 2000 },
                12: { segmentLength: 1000 },
                13: { segmentLength: 500 },
                14: { segmentLength: 250 },
                15: { segmentLength: 100 },
                16: { segmentLength: 30 },
                17: { segmentLength: 15 },
            };
            if (!levelType[level]) return [];
            //值越小箭头越多
            segmentLength = levelType[level].segmentLength;
            var data = mapUtils.turf.misc.lineChunk_sync(paths, segmentLength, options);

            let pointList = [];
            data.forEach(item => {
                let coor = item[item.length - 1];
                let point = this.getNearPoint(paths, {
                    x: coor[0],
                    y: coor[1],
                });

                pointList.push(point);
            });

            let point, angle;
            for (let i = 0; i < pointList.length; i++) {
                point = pointList[i];
                if (pointList[i + 1]) {
                    angle = this.getPointAngle(point, pointList[i + 1]);
                    point.symbol = Object.assign({}, symbol);
                    point.symbol.angle = angle;
                }
            }
            pointList.length = pointList.length - 1;
            return pointList;
        },

        //获取点到线上的最近点
        getNearPoint(paths, point) {
            var mapUtils = this.mapUtils;
            var nearestData = mapUtils.turf.misc.nearestPointOnLine_sync(mapUtils, paths, point, {
                units: 'meters',
            });
            return nearestData;
        },
        //设置点位角度
        getPointAngle(item, nextItem) {
            var mapUtils = this.mapUtils;
            var bearing = mapUtils.turf.measurement.rhumbBearing_sync(mapUtils, item, nextItem, {});
            return bearing;
        },
        getGraphicLocation: function (esriEvent) {
            if (!esriEvent || !esriEvent.mapPoint) {
                return;
            }
            var geometry = esriEvent.mapPoint || {};

            var lngFieldName = 'x';
            var latFieldName = 'y';
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            location.sr = geometry.spatialReference;
            return location;
        },
        _creatLabelData: function (mapUtils, graphics) {
            var me = this;
            if (!mapUtils) {
                return;
            }
            var map = mapUtils.getMap();
            if (!map) {
                return;
            }
            if (!me.labelOptions) {
                return;
            }
            var symbol = me.labelOptions.labelSymbol;

            var labelClass = me._changeSymbol(symbol.labelClass);

            me.__textGraphics = [];
            var pathIndex = 0;
            var pointIndex = 0;

            graphics.map(function (item) {
                if (item._shape) {
                    var attributes = JSON.parse(JSON.stringify(item.attributes));
                    if (attributes) {
                        if (!attributes.x || !attributes.y) {
                            pointIndex = ~~(item.geometry.paths[pathIndex].length / 2);
                            var xy = item.geometry.getPoint(pathIndex, pointIndex);
                            attributes.x = xy.x;
                            attributes.y = xy.y;
                        }
                        var label = attributes[me.labelOptions.textField];
                        if (label && label !== '--') {
                            attributes.symbol = attributes.labelSymbol || {
                                html: `<div class="${labelClass}">${label}</div>`,
                            };
                            me.__textGraphics.push(attributes);
                        }
                    }
                }
            });
        },
        /*鼠标移入后设置高亮样式*/
        _setHighlightSymbol: function (e, mapUtils) {
            if (!this.highlightOptions || !this.highlightOptions.visible) {
                return;
            }
            if (!e.graphic._defaultSymbol) {
                e.graphic._defaultSymbol = e.graphic.symbol;
            }
            var symbol = e.graphic.symbol;
            if (this.highlightOptions.symbol) {
                symbol = mapUtils.createSymbol(mapUtils, this.highlightOptions.symbol);
                e.graphic.setSymbol(symbol);
            }
        },
        /*鼠标移出后还原样式*/
        _setDefaultSymbol: function (e) {
            if (!this.highlightOptions || !this.highlightOptions.visible) {
                return;
            }
            var symbol = e.graphic._defaultSymbol;
            if (!symbol) {
                return;
            }

            e.graphic.setSymbol(symbol);
        },

        //统一移除子类中的事件 by MHQ
        _removeHandle() {
            if (this._handleList && this._handleList.length) {
                this._handleList.forEach(handle => {
                    if (handle && $.isFunction(handle.remove)) {
                        handle.remove();
                        handle = null;
                    }
                });
            }
        },
        createSymbol(t = { type: null }) {
            if (t.type == 'esriSLS') {
                return new SimpleLineSymbol(t);
            } else if (t.type == 'esriCLS') {
                return new CartographicLineSymbol(t);
            } else {
                let symbol = new SimpleLineSymbol({
                    type: 'esriSLS',
                    style: 'esriSLSSolid',
                    color: [115, 76, 0, 255],
                    width: 2,
                });
                return symbol;
            }
        },
        createPolyline(t, a = {}) {
            var o = a.pathsFieldName || 'paths',
                i = a.sr || this.mapUtils.getSpatialReference();
            let g = new Polyline({
                paths: t[o],
                spatialReference: i,
            });
            return g;
        },
        createGraphic(t) {
            t = Object.assign(
                { geometry: null, symbol: null, attributes: null, infoTemplate: null },
                t
            );
            let g = new Graphic(t.geometry, t.symbol, t.attributes, t.infoTemplate);
            return g;
        },
    });
    return PolylineLayer;
});
